package com.lwl.concurrency.collection;

import java.util.Map;
import java.util.concurrent.ConcurrentNavigableMap;
import java.util.concurrent.ConcurrentSkipListMap;

/**
 * 线程安全非阻塞可遍历map
 * <pre>
 * ConcurrentSkipListMap，它实现了非阻塞列表且拥有ConcurrentNavigableMap的行为。
 * 在内部实现中，它使用Skip List来存储数据。Skip List是基于并行列表的数据结构，
 * 它允许我们获取类似二叉树的效率。使用它，你可以得到一个排序的数据结构，
 * 这比排序数列使用更短的访问时间来插入、搜索和删除元素。
 * 往map中插入数据时，它使用key来排序它们，所以，所有元素将是有序的
 * </pre>
 *
 * @author lwl  2018年1月16日 下午10:48:39
 */
public class ConcurrentSkipListMapTest {

    static class Contact {
        private String name;
        private String phone;

        public Contact(String name, String phone) {
            this.name = name;
            this.phone = phone;
        }

        public String getName() {
            return name;
        }

        public String getPhone() {
            return phone;
        }
    }

    static class Task implements Runnable {

        private ConcurrentSkipListMap<String, Contact> map;
        private String id;

        public Task(ConcurrentSkipListMap<String, Contact> map, String id) {
            this.map = map;
            this.id = id;
        }

        @Override
        public void run() {
            for (int i = 0; i < 1000; i++) {
                Contact contact = new Contact(id, Integer.toString(i + 100));
                map.put(id + contact.getPhone(), contact);
            }

        }
    }

    public static void main(String[] args) {
        ConcurrentSkipListMap<String, Contact> map = new ConcurrentSkipListMap<>();
        Thread[] threads = new Thread[26];
        int counter = 0;
        for (char i = 'A'; i <= 'Z'; i++) {
            String s = String.valueOf(i);
            System.out.println(s+".......................");
            Task task = new Task(map, s);
            threads[counter] = new Thread(task);
            threads[counter].start();
            counter++;
        }

        for (int i = 0; i < 26; i++) {
            try {
                threads[i].join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.printf("Main: Size of the map: %d\n", map.size());
        Map.Entry<String, Contact> element;
        Contact contact;
        element = map.firstEntry();
        contact = element.getValue();
        System.out.printf("Main: First Entry: %s: %s\n", contact.getName(), contact.getPhone());
        element = map.lastEntry();
        contact = element.getValue();
        System.out.printf("Main: Last Entry: %s: %s\n", contact.getName(), contact.getPhone());
        System.out.printf("Main: Submap from A1996 to B1002: \n");
        ConcurrentNavigableMap<String, Contact> submap = map.subMap("A1001", "A1002");
        submap.put("A1001",new Contact("ahahah","ahahaah"));
        submap = map.subMap("A1001", "A1002");
        do {
            element = submap.pollFirstEntry();
            if (element != null) {
                element.getKey();
                contact = element.getValue();
                System.out.printf("%s: %s\n", contact.getName(), contact.getPhone());
            }
        } while (element != null);
    }


}
